
/*
 * 基于 koa 来优化 石头剪刀布 的游戏
 *
 * 优点
 * - 实现异步中间件，async await（异步情况下也符合洋葱模型）
 * - 比 express 更极致的 request/response 简化，用 ctx 来代替
 *   - ctx.status、ctx.body
 * - 不包含路由，所以需要同步引入 koa-mount 来实现
 * - 精简内核，所有功能都放到中间件中去实现
 * 
 * mount-koa
 * - mount 后面只能挂载一个中间件（也就是一个 function），如果有多个，则可以抽出一个新的中间件实例， 用 mount 来挂载，这样可以将逻辑分的更细致
 * - 存在的问题：
 *   - mount 在判断路由时，用的是 是否包含，所以 '/' 需要写在 '/game' 之后，否则全都走到 '/' 中间件中去了（express 不存在这个问题）
 */

 const koa = require('koa')
 const mount = require('koa-mount')
 const fs = require('fs')
 const game = require('../commonJS/gameLib')

 // 玩家胜率次数，如果超过 3，则后续服务器的请求都返回 500
var playWinCount = 0
// 玩家上一次游戏动作
var lastPlayAction = null
// 玩家连续出同一动作的次数，如果超过 3 次
var sameCount = 0

 // 没有实现构造器，所以需要 new
 const app = new koa()

 app.use(
     mount('/favicon.ico', function(ctx){
        ctx.status = 200
     })
 )

 // 新建 koa 实例，再将 游戏逻辑分为 3 层处理，更加清晰
 const gameKoa = new koa()
 app.use(
     mount('/game', gameKoa)
 )
 gameKoa.use(
     async function(ctx, next) {
        if (playWinCount >= 3) {
            ctx.status = 500
            ctx.body = '你耍赖，我再也不和你玩了~~~'
            return
        }
        await next()
        if (ctx.playerWon) {
            playWinCount++
        }
     }
 )
 gameKoa.use(
    async function(ctx, next) {
        const query = ctx.query
        const playAction = query.action
        if (sameCount == 99) {
            ctx.status = 500
            ctx.body = '你耍赖，我再也不和你玩了~~~'
            return
        }
        if (lastPlayAction && lastPlayAction == playAction) {
            sameCount++
        }else {
            sameCount = 0
        }
        lastPlayAction = playAction
        if (sameCount >= 3) {
            ctx.status = 400
            ctx.body = '没意思，不许出一样的~~~'
            sameCount = 99
            return;
        }
        ctx.playAction = playAction
        await next()
    }
 )
 gameKoa.use(
    async function(ctx) {  
        const playAction = ctx.playAction
        const gameResult = game(playAction)
        await new Promise(resolve => {
            setTimeout(() => {
                ctx.status = 200
                if (gameResult == 0) {
                    ctx.body = '平局！'
                }else if (gameResult == -1) {
                    ctx.playerWon = true
                    ctx.body = '你赢了！'
                }else {
                    ctx.body = '你输了！'
                }
                resolve()
            }, 500);
        })
    }
 )

 app.use(
     mount('/', function(ctx){
        ctx.body = fs.readFileSync(__dirname + '/game.html', 'utf-8')
     })
 )
 
 app.listen(3000)
